﻿using System;
using System.Collections.Generic;

using System.Windows;
using System.Windows.Controls;

using System.Windows.Input;

using System.Windows.Threading;
using System.Windows.Media.Animation;

using System.Threading;

using EagleJournal.Components;

using EagleJournalBE.Database.Tables;

namespace EagleJournal
{
	public partial class MainWindow : Window
	{
        public static readonly RoutedCommand 
            NotificationOpen                = new RoutedCommand();

        int                     notificationHead    = 0;
        bool                    dataLoaded          = false;
        List<string>            notificationStack   = new List<string>();

        DispatcherTimer         notificationCheck;
        DispatcherTimer         notificationDisplay;
        DispatcherTimer         notificationLifetimeTimer;

        Storyboard              showNotifCharm;
        Storyboard              hideNotifCharm;

        Storyboard              showNotifDialog;
        Storyboard              hideNotifDialog;

        Storyboard              loginToMain;
        Storyboard              mainToLogin;

        Storyboard              mainToClient;
        Storyboard              clientToMain;

        Storyboard              mainToOrders;
        Storyboard              ordersToMain;

        Storyboard              showHelp;
        Storyboard              hideHelp;

        Storyboard              showMessage;
        Storyboard              hideMessage;

        Storyboard              exitApp;

		public                  MainWindow                              ()
		{
			this.InitializeComponent();

            KeyBinding shortcut = new KeyBinding(NotificationOpen, new KeyGesture(Key.N, ModifierKeys.Control));
            this.InputBindings.Add(shortcut);

            notificationLifetimeTimer = new DispatcherTimer(DispatcherPriority.Send, this.Dispatcher);
            notificationLifetimeTimer.Interval = new TimeSpan(0, 0, 20);
            notificationLifetimeTimer.Tick     += new EventHandler((o, e) =>
            {
                this.BeginStoryboard(hideNotifCharm);
                this.notificationLifetimeTimer.Stop();
            });

            notificationCheck = new DispatcherTimer(DispatcherPriority.Normal, this.Dispatcher);
            notificationCheck.Interval = new TimeSpan(1, 0, 0);
            notificationCheck.Tick += new EventHandler((o, e) =>
            {
                Dispatcher.Invoke(new Action(() =>
                {
                    NotificationCheck();

                }), DispatcherPriority.Normal, null);
            });

            notificationDisplay = new DispatcherTimer(DispatcherPriority.Send, this.Dispatcher);
            notificationDisplay.Interval = new TimeSpan(0, 5, 0);
            notificationDisplay.Tick += ((o, e) =>
                {
                    EagleNotification.ShowAlert("PO deadline: " + notificationStack[notificationHead++]);

                    notificationHead = notificationHead % notificationStack.Count;
                });
		}

        public override void    OnApplyTemplate                         ()
        {
            base.OnApplyTemplate();

            #region Load storyboards

            showNotifCharm              = (Storyboard)this.FindResource("ShowNotifCharm");
            hideNotifCharm              = (Storyboard)this.FindResource("HideNotifCharm");
            hideNotifCharm.Completed    += new EventHandler((o, sbe) =>
            {
                this.RootGrid.Children.Remove(this.NotifCharm);
            });

            showNotifDialog             = (Storyboard)this.FindResource("ShowNotifDialog");
            hideNotifDialog             = (Storyboard)this.FindResource("HideNotifDialog");
            hideNotifDialog.Completed   += new EventHandler((o, sbe) =>
            {
                this.RootGrid.Children.Remove(this.Notif);
            });

            loginToMain                 = (Storyboard)this.FindResource("LoginToMain");
            loginToMain.Completed       += new EventHandler((o, sbe) =>
            {
                this.ContentGrid.Children.Remove(this.Login);
            });
            mainToLogin                 = (Storyboard)this.FindResource("MainToLogin");
            mainToLogin.Completed       += new EventHandler((o, sbe) =>
            {
                this.ContentGrid.Children.Remove(this.Main);
            });

            mainToClient                = (Storyboard)this.FindResource("MainToClient");
            mainToClient.Completed      += new EventHandler((o, sbe) =>
            {
                if (!this.ContentGrid.Children.Contains(this.Client))
                    this.ContentGrid.Children.Add(this.Client);

                this.ContentGrid.Children.Remove(this.Main);
            });
            clientToMain                = (Storyboard)this.FindResource("ClientToMain");
            clientToMain.Completed      += new EventHandler((o, sbe) =>
            {
                if (!this.ContentGrid.Children.Contains(this.Main))
                    this.ContentGrid.Children.Add(this.Main);

                this.ContentGrid.Children.Remove(this.Client);
            });

            mainToOrders                = (Storyboard)this.FindResource("MainToOrder");
            ordersToMain                = (Storyboard)this.FindResource("OrderToMain");
            ordersToMain.Completed      += new EventHandler((o, sbe) =>
            {
                if (!this.ContentGrid.Children.Contains(this.Main))
                    this.ContentGrid.Children.Add(this.Main);

                this.ContentGrid.Children.Remove(this.Order);
            });

            showMessage                 = (Storyboard)this.FindResource("ShowMessage");
            hideMessage                 = (Storyboard)this.FindResource("HideMessage");
            hideMessage.Completed       += new EventHandler((o, sbe) =>
            {
                this.RootGrid.Children.Remove(this.MessageBox);
            });

            exitApp                     = (Storyboard)this.FindResource("ExitApp");
            exitApp.Completed           += new EventHandler((o, sbe) =>
            {
                DispatcherTimer timer = new DispatcherTimer();
                timer.Interval = new TimeSpan(0, 0, 1);
                timer.Tick += new EventHandler((to, te) =>
                {
                    Application.Current.Shutdown();

                    timer.Stop();
                });
                timer.Start();
            });

            showHelp                    = (Storyboard)this.FindResource("ShowHelp");
            hideHelp                    = (Storyboard)this.FindResource("HideHelp");
            hideHelp.Completed          += new EventHandler((o, sbe) =>
            {
                this.ContentGrid.Children.Remove(this.Help);
            });

            #endregion

            #region Freeze storyboards

            showNotifCharm.Freeze();
            showNotifDialog.Freeze();

            hideNotifCharm.Freeze();
            hideNotifDialog.Freeze();

            loginToMain.Freeze();

            mainToClient.Freeze();
            clientToMain.Freeze();

            mainToOrders.Freeze();
            ordersToMain.Freeze();

            showHelp.Freeze();
            hideHelp.Freeze();

            showMessage.Freeze();
            hideMessage.Freeze();

            exitApp.Freeze();

            #endregion
        }

        private         void    RootWindow_Loaded                       (object sender, RoutedEventArgs e)
        {
            if (!this.dataLoaded)
            {
                this.ContentGrid.Children.Remove(this.Main);

                this.ContentGrid.Children.Remove(this.Client);
                this.ContentGrid.Children.Remove(this.Order);

                this.RootGrid.Children.Remove(this.Notif);
                this.RootGrid.Children.Remove(this.NotifCharm);

                this.RootGrid.Children.Remove(this.Help);

                this.RootGrid.Children.Remove(this.MessageBox);

                this.dataLoaded = true;

                this.notificationCheck.Start();
                this.notificationDisplay.Start();

                EagleMessageBox.Atttach(this.MessageBox);
                EagleNotification.Attach(this.NotifCharm);
                EagleNotificationPO.Attach(this.Notif);

                NotificationCheck();
            }
        }

        private         void    MessageBox_InvokeMessage                (object sender, RoutedEventArgs e)
        {
            if (this.MessageBox.Visibility == Visibility.Visible && this.RootGrid.Children.Contains(this.MessageBox))
                return;

            if (!this.RootGrid.Children.Contains(this.MessageBox))
                this.RootGrid.Children.Add(this.MessageBox);

            this.BeginStoryboard(showMessage);
        }
        private         void    MessageBox_InvokeDialogConfirm          (object sender, RoutedEventArgs e)
        {
            this.BeginStoryboard(hideMessage);
        }

        private         void    Login_InvokeSuccessfulLogin             (object sender, RoutedEventArgs e)
        {
            if (!this.ContentGrid.Children.Contains(this.Main))
                this.ContentGrid.Children.Add(this.Main);

            this.BeginStoryboard(loginToMain);

            EagleNotification.ShowAlert("Logged in as a <data reviewer/front desk user>. Welcome!");
        }

        private         void    Notif_InvokeNotificationCloseButton     (object sender, RoutedEventArgs e)
        {
            this.BeginStoryboard(hideNotifDialog);
        }

        private         void    NotifCharm_InvokeAlert                  (object sender, RoutedEventArgs e)
        {
            if (!this.RootGrid.Children.Contains(this.NotifCharm))
                this.RootGrid.Children.Add(this.NotifCharm);

            this.BeginStoryboard(showNotifCharm);
            this.notificationLifetimeTimer.Start();
        }
        private         void    NotifCharm_InvokeNotificationDismiss    (object sender, RoutedEventArgs e)
        {
            this.BeginStoryboard(hideNotifCharm);

            this.notificationLifetimeTimer.Stop();
        }

        private         void    Main_InvokeLogoutConfirmed              (object sender, RoutedEventArgs e)
        {
            if (!this.ContentGrid.Children.Contains(this.Login))
                this.ContentGrid.Children.Add(this.Login);

            this.BeginStoryboard(mainToLogin);
        }

        private         void    Main_InvokeButtonOrdersClicked          (object sender, RoutedEventArgs e)
        {
            if (!this.ContentGrid.Children.Contains(this.Order))
                this.ContentGrid.Children.Add(this.Order);

            this.BeginStoryboard(mainToOrders);
        }
        private         void    Main_InvokeButtonClientClicked          (object sender, RoutedEventArgs e)
        {
            if (!this.ContentGrid.Children.Contains(this.Client))
                this.ContentGrid.Children.Add(this.Client);

            this.BeginStoryboard(mainToClient);
        }
        private         void    Main_InvokeNotificationButtonClicked    (object sender, RoutedEventArgs e)
        {
            if (this.NotifCharm.Visibility == Visibility.Visible)
                this.BeginStoryboard(hideNotifCharm);

            if (!this.RootGrid.Children.Contains(this.Notif))
                this.RootGrid.Children.Add(this.Notif);

            this.BeginStoryboard(showNotifDialog);
        }

        private         void    Order_InvokeBackButton                  (object sender, RoutedEventArgs e)
        {
            if (!this.ContentGrid.Children.Contains(this.Main))
                this.ContentGrid.Children.Add(this.Main);

            this.BeginStoryboard(ordersToMain);
        }
        private         void    Client_InvokeBackButton                 (object sender, RoutedEventArgs e)
        {
            if (!this.ContentGrid.Children.Contains(this.Main))
                this.ContentGrid.Children.Add(this.Main);

            this.BeginStoryboard(clientToMain);
        }

        private         void    Login_InvokeExitButtonClicked           (object sender, RoutedEventArgs e)
        {
            if (this.NotifCharm.Visibility == Visibility.Visible)
                this.BeginStoryboard(hideNotifCharm);

            this.BeginStoryboard(exitApp);
        }
        private         void    Login_InvokeHelpButtonClicked           (object sender, RoutedEventArgs e)
        {
            if (!this.ContentGrid.Children.Contains(this.Help))
                this.ContentGrid.Children.Add(this.Help);

            this.BeginStoryboard(showHelp);
        }

        private         void    Help_InvokeBackButtonClicked            (object sender, RoutedEventArgs e)
        {
            this.BeginStoryboard(this.hideHelp);
        }

        void                    NotificationShownExecuted               (object target, ExecutedRoutedEventArgs e)
        {
            if (this.Notif.Visibility == Visibility.Visible)
                this.BeginStoryboard(hideNotifDialog);
            else
                Main_InvokeNotificationButtonClicked(target, null);
        }
        void                    NotificationShownCanExecute             (object target, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private         void    NotificationCheck                       ()
        {
            EagleNotificationPO.ClearNotif();
            this.notificationStack.Clear();

            TableDeadline deadline = new TableDeadline();
            deadline.Refresh();

            TablePurchaseOrder po = new TablePurchaseOrder();
            po.Refresh();

            foreach (List<object> row in deadline.TableData)
            {
                // check if row[2] -> DateTime falls within DateTime.Now + 6 days
                if (DateTime.FromBinary((long)Convert.ToInt64(row[1])).Date > DateTime.Now)
                    if ((DateTime.FromBinary((long)Convert.ToInt64(row[1])) - DateTime.Now).TotalDays <= 6)
                    {
                        // if yes get PO that is associated with it
                        po.Filter("purchaseOrderDeadlineID = " + row[0]);

                        if (po.TableData.Count > 0)
                        {
                            // then get the description of that PO
                            string description = (string)po.TableData[0][5];

                            // then add the description to the notification stack
                            this.notificationStack.Add(description);
                            EagleNotificationPO.AddNotif(description);
                        }
                    }
            }
        }

        private void RootWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (this.NotifCharm.Visibility == Visibility.Visible)
                this.BeginStoryboard(hideNotifCharm);

            this.BeginStoryboard(exitApp);

            e.Cancel = true;
        }
	}
}
